#include "sys/socket.h"
#include "netinet/in.h"
#include "stdio.h"
#include "string.h"
#include "errno.h"
#include "unistd.h"

#include "tcp_funs.h"

#define BUFSIZE 5000

void parallel_tcp_server()
{
	  int listen_fd, conn_fd;
	  struct sockaddr_in server_addr, remote_addr;
	  int bind_ret_val, listen_ret_val, send_ret_val, recv_ret_val;
	  int sockaddr_len, send_len;
	  char recv_buf[BUFSIZE];
	  pid_t pid;
	  int conn_count = 0;

	  sockaddr_len = sizeof(struct sockaddr);

	  listen_fd = socket(PF_INET, SOCK_STREAM, 0);
	  if(-1 == listen_fd) {
		  printf("&parallel_tcp_server: fail to create socket, program exit.\n");
		  printf("&parallel_tcp_server: The failure reason is %d.\n", errno);
		  exit(0);
	  }

	  memset(&server_addr, 0, sizeof(server_addr));
	  server_addr.sin_family = AF_INET;
	  server_addr.sin_port = htons(8000);
	  server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

	  bind_ret_val = bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
	  if(-1 == bind_ret_val) {
		  printf("&parallel_tcp_server: fail to bind socket to local address, program exit.\n");
		  printf("&parallel_tcp_server: The failure reason is %d.\n", errno);
		  exit(0);
	  }

	  listen_ret_val = listen(listen_fd, 3);
	  if(-1 == listen_ret_val) {
			printf("&parallel_tcp_server: fail to listen on the socket, program exit.\n");
			printf("&parallel_tcp_server: The failure reason is %d.\n", errno);
			exit(0);
	  }

	  while(1) {
		  	printf("Listenning to socket......\n");
		  	printf("The current maximum connection number is %d", conn_count);
			conn_fd = accept(listen_fd, (struct sockaddr*)&remote_addr, &sockaddr_len);
			if(-1 == conn_fd) {
				printf("&parallel_tcp_server: fail to accept for clients, program exit.\n");
				printf("&parallel_tcp_server: The failure reason is %d.\n", errno);
			}

			conn_count ++;

			if( 0 == (pid = fork()) ) {
				printf("&parallel_tcp_server: start a new child server process.\n");

				close(listen_fd);

				//doit
				send_len = strlen("Welcome you, this is server powered by mobile+.");
				send_ret_val = send(conn_fd, "Welcome you, this is server powered by mobile+.", send_len, 0);
				if(send_len != send_ret_val) {
				  printf("&parallel_tcp_server: fail to send welcome message from server, program exit.\n");
				  printf("&parallel_tcp_server: The failure reason is %d.\n", errno);
				  exit(0);
				}

				while( 0 < (recv_ret_val = recv(conn_fd, recv_buf, BUFSIZE, 0)) ) {
#ifdef DEBUG_TCP
					printf("&parallel_tcp_server: the return value of recv fun is :%d\n", recv_ret_val);
#endif
					recv_buf[recv_ret_val] = '\0';
					printf("&parallel_tcp_server %d: data reveived from remote address is: %s\n", (int)getpid(), recv_buf);
					send_ret_val = send(conn_fd, recv_buf, recv_ret_val, 0);
					if(recv_ret_val != send_ret_val) {
						printf("&parallel_tcp_server: fail to re-send data from remote, program exit.\n");
						printf("&parallel_tcp_server: The failure reason is %d.\n", errno);
						exit(0);
					}
				}
				if(-1 == recv_ret_val) {
					printf("&parallel_tcp_server %d: fail to receive data from the client, program exit.\n", (int)getpid());
					printf("&parallel_tcp_server %d: The failure reason is %d.\n", (int)getpid(), errno);
				}
				else if(0 == recv_ret_val) {
					printf("&parallel_tcp_server %d: the client has disconnect to server.\n", (int)getpid());
				}
#if DEBUG_TCP
				printf("&parallel_tcp_server: the return value of recv fun is :%d\n", recv_ret_val);
#endif

				close(conn_fd);
				printf("&parallel_tcp_server %d: close a existing child server process.\n", (int)getpid());
				exit(0);
			}

			close(conn_fd);
	  }

	  close(listen_fd);

	  return;
}
